import * as winston from 'winston';
import 'winston-daily-rotate-file';
import { WinstonModuleAsyncOptions } from 'nest-winston';
import { ConfigService } from '@nestjs/config';
import * as fs from 'node:fs';
import * as path from 'node:path';

export const winstonConfig: WinstonModuleAsyncOptions = {
  useFactory: (configService: ConfigService) => {
    // 获取日志文件路径配置
    const infoLogConfig = configService.get('application.logger.info');
    const errorLogConfig = configService.get('application.logger.error');

    // 确保日志目录存在
    const logDir = path.dirname(infoLogConfig.filename);
    if (!fs.existsSync(logDir)) {
      fs.mkdirSync(logDir, { recursive: true });
    }

    return {
      level: 'debug',
      levels: { ...winston.config.syslog.levels, sql: 8 },
      transports: [
        new winston.transports.DailyRotateFile({
          dirname: infoLogConfig.dirname || 'logs',
          filename: infoLogConfig.filename || 'application-%DATE%.log',
          datePattern: 'YYYY-MM-DD',
          maxSize: infoLogConfig.maxSize || '20m',
          maxFiles: infoLogConfig.maxFiles || '14d',
          format: winston.format.combine(
            winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
            winston.format.printf(({ timestamp, level, message, context = 'App' }) =>
              `[${timestamp}] [${level.toUpperCase()}] [${context}]: ${(message as string).replace(/\u001b\[[0-9;]*m/g, '')}`,
            ),
          ),
          level: 'info',
        }),

        new winston.transports.DailyRotateFile({
          dirname: errorLogConfig.dirname || 'logs',
          filename: errorLogConfig.filename || 'error-%DATE%.log',
          datePattern: 'YYYY-MM-DD',
          maxSize: errorLogConfig.maxSize || '20m',
          maxFiles: errorLogConfig.maxFiles || '30d',
          format: winston.format.combine(
            winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
            winston.format.printf(({ timestamp, level, message, stack, context = 'App' }) => {
              const formattedStack = stack ? `Stack Trace:\r\n${typeof stack === 'string' ? stack : JSON.stringify(stack, null, 2)}\r\n` : '';
              return `[${timestamp}] [${level.toUpperCase()}] [${context}]: ${(message as string).replace(/\u001b\[[0-9;]*m/g, '')}\r\n${formattedStack}`;
            }),
          ),
          level: 'error',
        }),

        new winston.transports.Console({
          format: winston.format.combine(
            winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
            winston.format.colorize({ all: true }),
            winston.format.printf(({ timestamp, level, message, context = 'App' }) =>
              `[${timestamp}] [${level}] [${context}]: ${message}`,
            ),
          ),
        }),
      ],
    };
  },
  inject: [ConfigService],
};
